package thread;


import java.util.PriorityQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 刘远望
 * Date: 2025-06-02
 * Time: 19:07
 */
// 这样的写法基于抽象类的方式定义 MyTimerTask
// 这样的定义虽然确实可以, 写起来有点麻烦.
// 还有另外的写法.
//abstract class MyTimerTask implements Runnable {
//    @Override
//    public abstract void run();
//}

//任务类 (自己实现定时器)
class MyTimerTask implements Comparable<MyTimerTask> {

    private Runnable task;

    private long time;

    public MyTimerTask(Runnable task, long time) {
        this.task = task;
        this.time = time;
    }

    public void run() {
        task.run();
    }

    public long getTime() {
        return time;
    }

    @Override
    public int compareTo(MyTimerTask o) {
        return (int) (this.time - o.time);
    }
}
//自己实现定时器
class MyTimer {

        private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();

        public Object locker = new Object();

        public void schedule(Runnable task, long delay) {
            synchronized (locker) {
                //以入队列的时间为基准
                MyTimerTask timerTask = new MyTimerTask(task, System.currentTimeMillis() + delay);
                queue.offer(timerTask);
                locker.notify();
            }
        }

        public MyTimer() {
            //创建一个线程，负责执行任务队列中的任务(定时器中仅有一个队列)
            Thread t = new Thread(() -> {
                while (true) {
                    try {
                        synchronized (locker) {
                            //取出队首元素
                            while (queue.isEmpty()) {//可以用while 多一次判断 防止notify后队列为空
                                locker.wait();//这里sleep不好，因为会阻塞线程，导致其他任务无法执行
                            }

                            MyTimerTask task = queue.peek();
                            if (System.currentTimeMillis() < task.getTime()) {
                                //当前任务时间，如果比系统时间大，说明任务执行的时机未到
                                locker.wait(task.getTime() - System.currentTimeMillis());
                            } else {
                                task.run();
                                queue.poll();
                            }
                        }
                    }catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });

            t.start();
        }
}
public class Demo37 {
    public static void main(String[] args) {
        //创建定时器
        MyTimer timer = new MyTimer();
        //定时执行任务
        timer.schedule(() -> System.out.println("Hello, 3000!"), 3000);
        //定时执行任务
        timer.schedule(() -> System.out.println("Hello, 2000!"), 2000);
        //定时执行任务
        timer.schedule(() -> System.out.println("Hello, 1000!"), 1000);


        //可以创建多个线程

        ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);

        executor.schedule(() -> System.out.println("Hello, 3000!"), 3, TimeUnit.SECONDS);
        /**
         * 一个线程负责扫描 扫描到需要多个要执行的任务，添加到线程池中，线程池的任务队列中，由多个线程负责执行任务。
         */

    }
}
